-------------------------------------------
--- Author: Ketho (EU-Boulderfist)		---
--- Created: 2011.07.06					---
--- License: Public Domain				---
--- Version: 0.22 [2011.07.10			---
-------------------------------------------
--- Curse			http://wow.curse.com/downloads/wow-addons/details/hideraidframe.aspx
--- WoWInterface	http://www.wowinterface.com/downloads/author-230732.html

------------------------------------------------------------------------------------
-- this addon might look totally ugly and overkill, which it actually is,
-- but it's designed for toggling the Raid Frame / Raid Manager
-- try to preserve your sanity when reading this, the code is a messy boolean hell ><
------------------------------------------------------------------------------------
-- This addon got major problems with joining/leaving groups while in/out combat

-- don't want to hardembed Ace3, don't know how to use SVN/Git
local AA = LibStub("AceAddon-3.0", true)
local AC = LibStub("AceConsole-3.0", true)
local ACR = LibStub("AceConfigRegistry-3.0", true)
local ACD = LibStub("AceConfigDialog-3.0", true)

-- stop here if we can't use Ace3
if not AA or not AC or not ACR or not ACD then
	CompactRaidFrameManager:UnregisterAllEvents()
	CompactRaidFrameManager.Show = function() end
	CompactRaidFrameManager:Hide()

	CompactRaidFrameContainer:UnregisterAllEvents()
	CompactRaidFrameContainer.Show = function() end
	CompactRaidFrameContainer:Hide()
	return
end

-- CompactRaidFrameContainer is parented to CompactRaidFrameManager
-- it's actually shown now, since it's now unparented and :IsShown() returns true
CompactRaidFrameContainer:SetParent(UIParent)

-- dirty hack, not sure why I can't get it to hide the "normal" way
if not InCombatLockdown() then
	CompactRaidFrameContainer:Hide()
end

HideRaidFrame = AA:NewAddon("HideRaidFrame", "AceEvent-3.0", "AceConsole-3.0")
local HRF = HideRaidFrame

local optionsFrame, profile
local delayRaidFrames, delayRaidManager, delayRaidContainer
local toggle
local InCombatLockdown = InCombatLockdown

local defaults = {
	profile = {
		RaidFrames = true,
	}
}

local function WaitingCombatNotifyMsg(variable)
	return variable and "  |cffFFFF00(Waiting for Combat)|r" or ""
end

local options = {
	type = "group",
	name = "",
	args = {
		RaidFrames = {
			type = "toggle",
			order = 1,
			descStyle = "",
			width = "full",
			name = function() return " |cffFF0000Hide|r "..RAID.." Frames"..WaitingCombatNotifyMsg(delayRaidFrames) end,
			get = function(i) return profile.RaidFrames end,
			set = function(i, v)
				profile.RaidFrames = v
				if InCombatLockdown() then
					delayRaidFrames = true
				else
					HRF:RaidManager(profile.RaidFrames or profile.RaidManager)
					HRF:RaidContainer(profile.RaidFrames or profile.RaidContainer)
				end
			end,
		},
		inlineGroup = {
			type = "group",
			order = 2,
			name = " ",
			inline = true,
			args = {
				Manager = {
					type = "toggle",
					order = 1,
					descStyle = "",
					width = "full",
					name = function() return " |cffFF0000Hide|r "..RAID.." Manager"..WaitingCombatNotifyMsg(delayRaidManager) end,
					get = function(i) return profile.RaidManager end,
					set = function(i, v)
						profile.RaidManager = v
						if InCombatLockdown() then
							delayRaidManager = true
						else
							HRF:RaidManager(profile.RaidFrames or profile.RaidManager)
						end
					end,
					disabled = function(i) return profile.RaidFrames end,
				},
				Container = {
					order = 2,
					type = "toggle",
					descStyle = "",
					width = "full",
					name = function() return " |cffFF0000Hide|r "..RAID.." Container"..WaitingCombatNotifyMsg(delayRaidContainer) end,
					get = function(i) return profile.RaidContainer end,
					set = function(i, v)
						profile.RaidContainer = v
						if InCombatLockdown() then
							delayRaidContainer = true
						else
							HRF:RaidContainer(profile.RaidFrames or profile.RaidContainer)
						end
					end,
					disabled = function(i) return profile.RaidFrames end,
				},
			},
		},
		descriptionOptions = {
			type = "description",
			order = 4,
			fontSize = "large",
			name = " |cff2E9AFE/hr options|r",
		},
	},
}

-- Ace3 stuff
function HRF:OnInitialize()
	self.db = LibStub("AceDB-3.0"):New("HideRaidFrameDB2", defaults, true)

	self.db.RegisterCallback(self, "OnProfileChanged", "RefreshConfig")
	self.db.RegisterCallback(self, "OnProfileCopied", "RefreshConfig")
	self.db.RegisterCallback(self, "OnProfileReset", "RefreshConfig")
	self:RefreshConfig()

	self.db.global.version = 0.22
	self.db.global.fileType = "Release"
	
	ACR:RegisterOptionsTable("HideRaidFrame_Main", options)
	ACR:RegisterOptionsTable("HideRaidFrame_Profiles", LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db))
	
	optionsFrame = ACD:AddToBlizOptions("HideRaidFrame_Main", "Hide|cffFFFFFFRaidFrame|r")
	ACD:AddToBlizOptions("HideRaidFrame_Profiles", "Profiles", "Hide|cffFFFFFFRaidFrame|r")

	self:RegisterChatCommand("hr", "SlashCommand")
	self:RegisterChatCommand("hrf", "SlashCommand")
	self:RegisterChatCommand("hideraid", "SlashCommand")
	self:RegisterChatCommand("hideraidframe", "SlashCommand")

	-- show/hide based on configuration
	if InCombatLockdown() then
		delayRaidFrames = true
	else
		self:RaidManager(self:OptionsFilter(profile.RaidManager))
		self:RaidContainer(self:OptionsFilter(profile.RaidContainer))
	end
end

function HRF:OnEnable()
	self:RegisterEvent("PLAYER_REGEN_ENABLED")
	self:RegisterEvent("PARTY_MEMBERS_CHANGED")
end

function HRF:RefreshConfig()
	profile = self.db.profile
end

	-----------------
	---- Prehooks ---
	-----------------

-- this is to prevent InterfaceOptionsFrameCancel,
-- and other stuff from showing/hiding it again
local oldCompactRaidFrameManager_Show = CompactRaidFrameManager.Show
function CompactRaidFrameManager:Show()
	if profile and not HRF:OptionsFilter(profile.RaidManager) and GetNumPartyMembers() > 0 then
		oldCompactRaidFrameManager_Show(self)
	--	print("|cffFFFF00Raid|rManager: |cffB6CA00Show|r", profile.RaidManager)
	end
end

local oldCompactRaidFrameManager_Hide = CompactRaidFrameManager.Hide
function CompactRaidFrameManager:Hide()
	if profile and HRF:OptionsFilter(profile.RaidManager) then
		oldCompactRaidFrameManager_Hide(self)
	--	print("|cffFFFF00Raid|rManager: |cffFF2424Hide|r", profile.RaidManager)
	end
end

local oldCompactRaidFrameContainer_Show = CompactRaidFrameContainer.Show
function CompactRaidFrameContainer:Show()
	if profile and not HRF:OptionsFilter(profile.RaidContainer) and GetNumPartyMembers() > 0 then
		oldCompactRaidFrameContainer_Show(self)
	--	print("|cffFFFF00Raid|rContainer: |cffB6CA00Show|r", profile.RaidContainer)
	end
end

local oldCompactRaidFrameContainer_Hide = CompactRaidFrameContainer.Hide
function CompactRaidFrameContainer:Hide()
	if profile and HRF:OptionsFilter(profile.RaidContainer) then
		oldCompactRaidFrameContainer_Hide(self)
	--	print("|cffFFFF00Raid|rContainer: |cffFF2424Hide|r", profile.RaidContainer)
	end
end

	---------------
	---- Events ---
	---------------

local CRFM_Events = {
	"DISPLAY_SIZE_CHANGED",
	"UI_SCALE_CHANGED",
	"RAID_ROSTER_UPDATE",
	"UNIT_FLAGS",
	"PLAYER_FLAGS_CHANGED",
	"PLAYER_ENTERING_WORLD",
	"PARTY_LEADER_CHANGED",
	"RAID_TARGET_UPDATE",
	"PLAYER_TARGET_CHANGED",
	"PARTY_MEMBERS_CHANGED",
}

local CRFC_Events = {
	"RAID_ROSTER_UPDATE",
	"PARTY_MEMBERS_CHANGED",
	"UNIT_PET",
}

	--------------------
	---- Show / Hide ---
	--------------------

function HRF:RaidManager(hide)
	if hide then
		CompactRaidFrameManager:UnregisterAllEvents()
		CompactRaidFrameManager:Hide()
	--	print("|cffFF2424Disabling|r: |cffFFFF00CompactRaidFrame|rManager")
	else
		for _, v in ipairs(CRFM_Events) do
			CompactRaidFrameManager:RegisterEvent(v)
		end
		CompactRaidFrameManager:Show()
	--	print("|cffB6CA00Enabling|r: |cffFFFF00CompactRaidFrame|rManager")
	end
end

function HRF:RaidContainer(hide)
	if hide then
		CompactRaidFrameContainer:UnregisterAllEvents()
		CompactRaidFrameContainer:Hide()
	--	print("|cffFF2424Disabling|r: |cffFFFF00CompactRaidFrame|rContainer")
	else
		for _, v in ipairs(CRFC_Events) do
			CompactRaidFrameContainer:RegisterEvent(v)
		end
		CompactRaidFrameContainer:Show()
	--	print("|cffB6CA00Enabling|r: |cffFFFF00CompactRaidFrame|rContainer")
	end
end

function HRF:OptionsFilter(option)
	return profile.RaidFrames or option
end

local function toggleState(option)
	if option then
		option = false
	else
		option = true
	end
end

-- leaving combat
function HRF:PLAYER_REGEN_ENABLED()
	if delayRaidFrames then
		if not notoggle then
			toggleState(profile.RaidFrames)
		end
		HRF:RaidManager(self:OptionsFilter(profile.RaidManager))
		HRF:RaidContainer(self:OptionsFilter(profile.RaidContainer))
	else
		if delayRaidManager then
			toggleState(profile.RaidManager)
			HRF:RaidManager(self:OptionsFilter(profile.RaidManager))
		end
		if delayRaidContainer then
			toggleState(profile.RaidContainer)
			HRF:RaidContainer(self:OptionsFilter(profile.RaidContainer))
		end
	end
	delayRaidFrames, delayRaidManager, delayRaidContainer, notoggle = false, false, false, false
	ACR:NotifyChange("HideRaidFrame_Main")
end

-- check if player joins/leaves groups
function HRF:PARTY_MEMBERS_CHANGED()
	-- does not account for when in combat .. too confused with the toggle functionality everywhere
	-- might need a throttle; this is kinda ugly actually; not sure if also need to unregister the events
	if InCombatLockdown() then
		notoggle = true
		delayRaidFrames = true
	else
		if GetNumPartyMembers() == 0 then
			oldCompactRaidFrameManager_Hide(CompactRaidFrameManager)
			oldCompactRaidFrameContainer_Hide(CompactRaidFrameContainer)
		else
			HRF:RaidManager(self:OptionsFilter(profile.RaidManager))
			HRF:RaidContainer(self:OptionsFilter(profile.RaidContainer))
		end
	end
end

function HRF:SlashCommand(input)
	if input == "options" or input == "option" or input == "o" then
		InterfaceOptionsFrame_OpenToCategory(optionsFrame)
		profile.firstRun = true
	else
		if not profile.firstRun then
			profile.firstRun = true
			self:Print("You can open the options with |cff2E9AFE/hr options|r")
		end
		-- for some reason I can't just use the following, it won't work: toggleState(profile.RaidFrames)
		-- I'm also not sure why/if this particular toggle code messes up the other "toggle functionality" in PLAYER_REGEN_ENABLED
		if profile.RaidFrames then
			profile.RaidFrames = false
		else
			profile.RaidFrames = true
		end
		if InCombatLockdown() then
			delayRaidFrames = true
			print("|cffFFFF00Raid Frame|r:", profile.RaidFrames and "|cffFF2424Disabling|r after Combat" or "|cffADFF2FEnabling|r after Combat")
		else
			print("|cffFFFF00Raid Frame|r:", profile.RaidFrames and "|cffFF2424Disabled|r" or "|cffADFF2FEnabled|r")
			self:RaidManager(self:OptionsFilter(profile.RaidManager))
			self:RaidContainer(self:OptionsFilter(profile.RaidContainer))
		end
		ACR:NotifyChange("HideRaidFrame_Main")
	end
end